function [s_out,g] = linear_mmse_precode(s_in,h,noise,power,nr,nt)

v=noise*diag(diag(ones(nr)));
Rnn=v*v';
[V,gamma]=eig(h'*inv(Rnn)*h,'nobalance');
B=rank(h);
Ib=diag(diag(ones(B)));
W=Ib;

p=gamma*gamma;
p0=nt*power;
p_order=sort(diag(p),1,'descend');


phi_f=zeros(B,B);
found_u=0;
k=B;
while(found_u==0)
	sum1=0;
	for m=1:k
		sum1=sum1 + 1/sqrt(gamma(m,m)) * sqrt(W(m,m));
	end
	sum2=0;
	for m=1:k
		sum2=sum2+ gamma(m,m)^-1;
	end
	u=(sum1 / (p0 + sum2))^2;
	if(u <= p_order(k))
		found_u=1;
	else
		phi_f(k,k)=0;
		k=k-1;
	end
end
phi_f=sqrt( ( inv(sqrt(u)) * inv(sqrt(gamma)) - inv(gamma) ) );
phi_g=sqrt( ( inv(sqrt(u)) * inv(sqrt(gamma)) - u*inv(gamma)) ) * inv(sqrt(gamma));


g=phi_g*V'*h'*inv(Rnn);
f=V*phi_f;
s_out=f*s_in;

